-
Notifications
You must be signed in to change notification settings - Fork 8k
drivers: eth_xmc4xxx: Add option to load MAC address from EEPROM #74835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does an ethernet driver need to know where the mac address is coming from?
If you need this, you should implement/use the set_config
from the ethernet driver API.
I think the driver works ok with this respect, it implements the set_config which then sets the MAC address. This change is figuring out from where the mac address is generated from in driver init which is then setting the initial value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be built in CI, maybe add a case for build_only
tests?
drivers/ethernet/eth_xmc4xxx.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put the compile check around the function.
#if DT_INST_NODE_HAS_PROP(0, mac_eeprom)
static int eth_xmc4xxx_get_mac_address_eeprom(const struct device *dev)
{
struct eth_xmc4xxx_data *dev_data = dev->data;
const struct device *eeprom_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, mac_eeprom));
int ret;
if (!device_is_ready(eeprom_dev)) {
LOG_ERR("EEPROM device not ready.");
return -ENODEV;
}
ret = eeprom_read(eeprom_dev, CONFIG_ETH_XMC4XXX_MAC_EEPROM_ADDRESS, dev_data->mac_addr,
sizeof(dev_data->mac_addr));
if (ret < 0) {
LOG_ERR("Error reading MAC address from EEPROM [%d]", ret);
}
return ret;
}
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my patch returning -ENODEV makes using the function cleaner and the compiler optimizes out the function when the node is not in the devicetree.
drivers/ethernet/Kconfig.xmc4xxx
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be mixing Kconfig with device tree properties, it should be possible to have this added in the device tree:
mac-eeprom = <&eeprom 0x00>;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pdgendt that would mean I'd have to modify the binding of the eeprom to add the -cells property?
@henrikbrixandersen would this be acceptable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are to do this (and not just rely on an application loading the board-specific MAC address from wherever and configuring the network interface), I'd prefer we align with how the Linux kernel devicetree bindings do this.
Something along the lines of:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pdgendt, unless I'm missing something, it is the binding of the referenced node that describes how the specifier entries are parsed. (i.e. all the gpio and dma examples).
https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/devicetree/gpio.h#L69
From this example it's the gpio binding that needs to define gpio-cells.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Please see the section on specifier spaces further down that page.
I'd still prefer using the same specifier space as the Linux kernel nvmem consumer bindings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@henrikbrixandersen, I'll work on the nvmem consumer binding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@henrikbrixandersen this an example from linux that matches what I'm trying to do:
But I have a devicetree question, what would be the default compatible of mac_address in this case? I tried the same approach in zephyr. It works, but it doesn't say which compatible was used for this node:
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
When testing on the sam_v71_xult board I found that the ethernet did not work independent of my change. The read MAC address from the EEPROM chip is the same before and after the change in this PR. |
Adds property nvmem-cells for referencing a node that stores some configuration information. A typical use case is the reading of MAC address from an EEPROM device. The referenced node is child of the non-volatile memory device. The address of the referenced node stores address/offset where the configuration is stored. Th nvmem-cells phandle could be pointing to a child of an eeprom node or an efuse register. Currently it is upto the devicetree driver to call the correct API for reading the configuration data. Future work could be to write an nvmem-producer driver abstraction that calls correct api for flash/eeprom. Signed-off-by: Andriy Gelman <[email protected]>
Adds an option to load the MAC address from an external EEPROM chip, for example from Microchip 25AA02E48 (atmel,at25) which come pre-programmed with a unique MAC. The priority for setting the MAC address in the driver is: (1) local-mac-address from devicetree (2) Eeprom address (3) Random address Signed-off-by: Andriy Gelman <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on sam_v71_xult/samv71q21 samples/net/cloud/tagoio_http_post.
@henrikbrixandersen, could you have another look, please? |
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
@henrikbrixandersen, could you have another look when you have a moment please |
Size (in bytes) of the internal EEPROM address. | ||
|
||
endif # ETH_SAM_GMAC_MAC_I2C_EEPROM | ||
Enable reading MAC address from external flash memory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enable reading MAC address from external flash memory. | |
Enable reading MAC address from external EEPROM memory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about the long delay in reviewing, somehow this fell off my radar.
It's looking really, really good. I'd like to try getting this into Zephyr v4.2, although we're a bit pressed on time for this.
The tests for the macros can come in after the feature freeze, if needed.
|
||
if (ret != 0) { | ||
LOG_ERR("I2C: failed to read MAC addr"); | ||
ret = eeprom_read(eeprom_dev, addr, mac_addr, 6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this at least check if the length matches that of the reg
property in the devicetree instead of hardcoding 6
with no check?
# Copyright (c) 2024, Andriy Gelman <[email protected]> | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
include: base.yaml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should include base.yaml
as it does not depend on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, we should have tests added for these macros.
CC: @maass-hamburg |
* eth: ethernet { | ||
* nvmem-cells = <&mac_address>; | ||
* nvmem-cell-names = "mac-address"; | ||
* }; | ||
* | ||
* Example usage: | ||
* | ||
* DT_NVMEM_DEV_BY_IDX(DT_NODELABEL(eth), 0) // DEVICE_DT_GET(DT_NODELABEL(mac_eeprom)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mixing tabs and spaces here
* eth: ethernet { | |
* nvmem-cells = <&mac_address>; | |
* nvmem-cell-names = "mac-address"; | |
* }; | |
* | |
* Example usage: | |
* | |
* DT_NVMEM_DEV_BY_IDX(DT_NODELABEL(eth), 0) // DEVICE_DT_GET(DT_NODELABEL(mac_eeprom)) | |
* eth: ethernet { | |
* nvmem-cells = <&mac_address>; | |
* nvmem-cell-names = "mac-address"; | |
* }; | |
* | |
* Example usage: | |
* | |
* DT_NVMEM_DEV_BY_IDX(DT_NODELABEL(eth), 0) // DEVICE_DT_GET(DT_NODELABEL(mac_eeprom)) |
* eth: ethernet@ { | ||
* ... | ||
* nvmem-cells = <&mac_address>; | ||
* nvmem-cell-names = "mac-address"; | ||
* ... | ||
* }; | ||
* | ||
* Example usage: | ||
* | ||
* DT_NVMEM_ADDR_BY_IDX(DT_NODELABEL(eth), 0) // 0xfa |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
* eth: ethernet@ { | |
* ... | |
* nvmem-cells = <&mac_address>; | |
* nvmem-cell-names = "mac-address"; | |
* ... | |
* }; | |
* | |
* Example usage: | |
* | |
* DT_NVMEM_ADDR_BY_IDX(DT_NODELABEL(eth), 0) // 0xfa | |
* eth: ethernet@ { | |
* ... | |
* nvmem-cells = <&mac_address>; | |
* nvmem-cell-names = "mac-address"; | |
* ... | |
* }; | |
* | |
* Example usage: | |
* | |
* DT_NVMEM_ADDR_BY_IDX(DT_NODELABEL(eth), 0) // 0xfa |
return 0; | ||
} | ||
|
||
static int eth_xmc4xxx_get_mac_address_eeprom(const struct device *dev) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of putting this in the drivers, wouldn't make sense to put this on a higher level and use eth_xmc4xxx_set_config
to apply?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be after iface init, but before iface up
I somehow missed the messages on this PR. Thank you to everyone for looking over. I'll send an updated version this week. |
@talih0 any update here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be implemented in a generic way, so that it uses the set_config api, so
that we don't have to duplicate code in every ethernet driver for that.
@talih0 Would you be open for pulling out the NVMEM provider/consumer commit of this PR and putting it its own PR? We have others requesting the same functionality for other use cases. If you wish, I can pull it out and submit it with your approval. |
Hello, |
I agree with others that this needs a more generic solution. The mac address can be stored/obtained in a myriad different ways, only known by the application. Can we use an application-supplied callback that supplies the mac address? Then we don't have to implement every possible way addresses could be obtained. |
I'll be working on a proof-of-concept using the NVMEM PR I opened this week. |
The nvmem solution is nice, but I don't think it fully removes the need for a plain "use this mac address" approach. The eeprom can be read protected or encrypted, or only store the last three bytes of the mac addres. The mac address could also be stored in a nand flash, or in a file on an emmc. We can't solve every corner case in the device tree. We also need a way for the application code to simply provide the mac address. |
There is already a api for that via set_config |
Is there? I struggle to find how to do this early enough that no ethernet frames with the wrong mac address leak out of the interface. |
True, but it's a start.
Yeah, this is difficult indeed, for that reason I've created #96598 as an alternative here, but still do it in the driver init. |
Adds an option to load the MAC address from an external EEPROM chip, for example from Microchip 25AA02E48 (atmel,at25) which come pre-programmed with a unique MAC.
The priority for setting the MAC address in the driver is: (1) local-mac-address from devicetree
(2) Eeprom address
(3) Random address